//
// Created by 98770 on 2023/6/22.
//

#include "libCache.h"
#if _WIN32

#elif __linux__

#endif
//存储每次刷新时需要删除的记录
char *toDelete[1000];
const int msize=1000;
int currentIndex=0;

bool createHashmap(struct hashmap_s *hashmap) {
    const unsigned initial_size = 100;
    if (0 != hashmap_create(initial_size, hashmap)) {
        // error--create hash map!
        return false;
    }
    return true;
}

bool putRecordInHashmap(struct hashmap_s *hashmap, char *domain, char *ip, uint32_t ttl) {
    //如果要插入的记录已经存在，则替换
//    EnterCriticalSection(&cacheLock);
    if (getRecordFromHashmap(hashmap, domain) != NULL)
        deleteRecordFromHashmap(hashmap, domain);
    //此处需要动态分配内存，会在删除记录时释放
    cacheNode *node = (struct cacheNode *) malloc(sizeof(struct cacheNode));
    if (node == NULL) {
//        LeaveCriticalSection(&cacheLock);  // 解锁
        printf("malloc failed!\n");
        return false;
    }
    strcpy(node->domain, domain);
    strcpy(node->ip, ip);
    node->ttl = ttl;
    if (0 != hashmap_put(hashmap, node->domain, strlen(node->domain), node)) {
        // error--put record in hash map!
//        LeaveCriticalSection(&cacheLock);
        return false;
    }
//    LeaveCriticalSection(&cacheLock);
    return true;
}

bool putRecordInHashmapWithNode(struct hashmap_s *hashmap, cacheNode *node){

    if (getRecordFromHashmap(hashmap, node->domain) != NULL)
        deleteRecordFromHashmap(hashmap, node->domain);
    if (0 != hashmap_put(hashmap, node->domain, strlen(node->domain), node)) {
        // error--put record in hash map!
        return false;
    }
    return true;
}
cacheNode *getRecordFromHashmap(struct hashmap_s *hashmap, char *domain) {
//    EnterCriticalSection(&cacheLock);
    void *node = hashmap_get(hashmap, domain, strlen(domain));
    if (node == NULL)
        return NULL;
//    LeaveCriticalSection(&cacheLock);
    return (struct cacheNode *) node;
}

bool deleteRecordFromHashmap(struct hashmap_s *hashmap, char *domain) {
    //先检查是否存在，如果hashmap中存在记录，需要释放内存
//    EnterCriticalSection(&cacheLock);
    cacheNode *node = getRecordFromHashmap(hashmap, domain);
    if (node == NULL){
//        LeaveCriticalSection(&cacheLock);
        return false;
    }
    else
        free(node);
    if (0 != hashmap_remove(hashmap, domain, strlen(domain))) {
        // error--delete record from hash map!
//        LeaveCriticalSection(&cacheLock);
        return false;
    }
//    LeaveCriticalSection(&cacheLock);
    return true;
}

bool loadCacheFromDisk(struct hashmap_s *hashmap, char *filename) {
    FILE *fp = fopen(filename, "r");
    if (fp == NULL) {
        printf("open cache file failed!\n");
        return false;
    }
    char domain[256], ip[256];
    while (fscanf(fp, "%s %s\n", domain, ip) != EOF) {
        putRecordInHashmap(hashmap, domain, ip, DEFAULT_TTL);
    }
    fclose(fp);
    return true;
}

//iterate函数用于hashmap_iterate，hashmap_iterate会对遍历到的每一个元素执行该函数的操作
//value指向遍历到的元素，context函数此处无用
static int iterate_for_store(void *const context, void *const value) {
    //把每条记录写入backup_cache.txt
    FILE *fp = fopen(DEFAULT_CACHE_FILE, "a");
    cacheNode *node = (struct cacheNode *) value;
    fprintf(fp, "%s %s\n", node->domain, node->ip);
    fclose(fp);
    //返回1让hashmap_iterate继续迭代
    return 1;
}

bool storeCacheToDisk(struct hashmap_s *hashmap) {
    //清空backup_cache.txt
    FILE *fp = fopen(DEFAULT_CACHE_FILE, "w");
    fclose(fp);
    cacheNode *value;
    if (0 != hashmap_iterate(hashmap, iterate_for_store, &value)) {
        // error--iterate hash map!
        return false;
    }
    return true;
}

static int iterate_for_destroy(void *const context, void *const value) {
    //释放每条记录的内存
    cacheNode *node = (struct cacheNode *) value;
    if (node != NULL)
        free(node);
    //返回1让hashmap_iterate继续迭代
    return 1;
}

bool destroyHashmap(struct hashmap_s *hashmap) {
    //此处遍历释放每条记录的内存
//    cacheNode *value;
//    if (0 != hashmap_iterate(hashmap, iterate_for_destroy, &value)) {
//        // error--iterate hash map!
//        return false;
//    }
    hashmap_destroy(hashmap);
    return true;
}

static int iterate_for_refresh(void *const context, void *const value) {
    //遍历每条记录，如果ttl小于0则加入toDelete中等待删除
    cacheNode *node = (struct cacheNode *) value;
    node->ttl--;
    if(node->ttl<=0){
        if(currentIndex!=msize) {
            toDelete[currentIndex] = node->domain;
            currentIndex++;
        }
    }
    return 1;
}
void refreshHashmap(struct hashmap_s*hashmap){
    cacheNode *value;
    currentIndex=0;
    //刷新ttl，找出需要删除的记录
    if (0 != hashmap_iterate(hashmap, iterate_for_refresh, &value)) {
        return;
    }
    for(int i=0;i<currentIndex;i++){
        deleteRecordFromHashmap(hashmap,toDelete[i]);
        toDelete[i]=NULL;
    }
    printf("Num of entries in dynamic cache: %d\n",hashmap_num_entries(hashmap));
    return;
}